package com.saturn.titan.core.repository.mybatis.base.sqlprovider;

import java.lang.reflect.Field;
import java.util.List;

import com.saturn.titan.core.bean.base.PageableBean;
import com.saturn.titan.core.datatable.DatatableOrder;
import com.saturn.titan.core.repository.mybatis.annotations.DbField;
import com.saturn.titan.core.repository.mybatis.annotations.DbRangeQueryField;
import com.saturn.titan.core.repository.mybatis.annotations.DbTable;
import com.saturn.titan.core.repository.mybatis.base.BaseDaoSqlProvider;

/**
 * 通用dao查询语句SQL生成器
 * 
 * 为根据主键查询实体，和根据传入实体查询实体列表的方法提供sql
 * 
 * @author lwh
 * 
 */
public class BaseDaoSelectSqlProvider extends BaseDaoSqlProvider {

	public String doBuildSql(Object param, Class<?> beanType) throws Exception {

		DbTable dbTableAnno = getDbTableAnno(beanType);
		
		String tableName = dbTableAnno.table();

		String sqlField = " ";
		String groupSqlField = " ";
		// 根据实体查询
		if (param instanceof Long) {
			List<Field> fields = getAllField(beanType);
			for (Field f : fields) {
				DbField field = f.getAnnotation(DbField.class);
				// 只对标注了为数据库字段的属性进行处理
				if (field == null) {
					continue;
				}
				sqlField += getColumnName(f, field) + ",";
			}
			return "select " + sqlField.substring(0, sqlField.length() - 1)
					+ " from " + tableName + " where id = " + param;
		} else {
			List<Field> beanFields = getAllField(beanType);

			String tmpColumnName = null;
			Class<?> tmpColumnType = null;
			String sqlWhere = "";
			boolean hasWhere = false;
			Object fieldValue = null;
			for (Field f : beanFields) {
				
				DbField field = f.getAnnotation(DbField.class);
				DbRangeQueryField queryField = f.getAnnotation(DbRangeQueryField.class);
				
				if(field == null && queryField == null){
					continue;
				}

				if(field != null){
					tmpColumnName = getColumnName(f, field);
					sqlField += "`" + tmpColumnName + "` as "+ f.getName() +",";
					groupSqlField += "`" + tmpColumnName + "`,";
				}else{
					tmpColumnName = queryField.column();
				}
				
				tmpColumnType = getColumnType(f, field);
				
				fieldValue = getColumnValue(param, f, beanType);

				if (fieldValue != null) {
					hasWhere = true;
					sqlWhere += tmpColumnName + " " + getOperation(queryField) + " " +
							 setupFieldValue(tmpColumnType, fieldValue) +
							 " and ";
				}
			}
			String sql = "select "
					+ (sqlField.length() > 1 ? sqlField.substring(0,
							sqlField.length() - 1) : "");
			sql += " from " + tableName;
			if (hasWhere) {
				sql += " where " + sqlWhere.substring(0, sqlWhere.length() - 4);
			}
			
			if(param instanceof PageableBean){
				PageableBean bean = (PageableBean)param;
				
				if(hasGroupInfo(bean)){
					
					String groupByColumns = " ";
					for(String col : bean.getGroupBy().getGroupBy()){
						groupByColumns += col+",";
					}
					
					if(bean.getGroupBy().getSumColumn() != null){
						for(String col : bean.getGroupBy().getSumColumn()){
							groupSqlField = groupSqlField.replaceAll("`"+col+"`", "sum("+col+") as "+col);
						}
					}
					
					if(bean.getGroupBy().getMaxColumn() != null){
						for(String col : bean.getGroupBy().getMaxColumn()){
							groupSqlField = groupSqlField.replaceAll("`"+col+"`", "max("+col+") as "+col);
						}
					}
					
					if(bean.getGroupBy().getMinColumn() != null){
						for(String col : bean.getGroupBy().getMinColumn()){
							groupSqlField = groupSqlField.replaceAll("`"+col+"`", "min("+col+") as "+col);
						}
					}
					
					if(bean.getGroupBy().getNullColumn() != null){
						for(String col : bean.getGroupBy().getNullColumn()){
							groupSqlField = groupSqlField.replaceAll("`"+col+"`", "'' as "+col);
						}
					}
					
					sql = "select " + sqlField.substring(0,sqlField.length() - 1) + 
							" from ( select " +groupSqlField.substring(0,groupSqlField.length() - 1) + 
									" from " + tableName;
					if (hasWhere) {
						sql += " where " + sqlWhere.substring(0, sqlWhere.length() - 4);
					}
					sql += " group by " + groupByColumns.substring(0,groupByColumns.length() - 1) + 
									") as T1";
					
					
				}
				
				String limitStr = "";
				
				if(bean.getOrderby() != null && !bean.getOrderby().isEmpty()){
					sql += " order by ";
					int i = 0;
					for(DatatableOrder info : bean.getOrderby()){
						sql += info.column + " " + info.dir;
						if(++i != bean.getOrderby().size()){
							sql += ",";
						}
					}
				}
				
				if(bean.getLimit() != null){
					limitStr += bean.getLimit();
					
					if(bean.getStart() != null){
						limitStr = bean.getStart()+","+limitStr;
					}
					
					sql += " limit " + limitStr;
				}
			}
			return sql;
		}
	}
	
}
